package com.cloud.shopping.pay.controller;

import com.alibaba.fastjson.JSON;
import com.cloud.shopping.constants.RocketConstants;
import com.cloud.shopping.pay.model.PayLog;
import com.cloud.shopping.pay.service.WeChatPayService;
import com.cloud.shopping.tool.RespResult;
import com.cloud.shopping.tool.Signature;
import com.cloud.shopping.tool.encry.Aes;
import com.cloud.shopping.tool.encry.Base64;
import com.cloud.shopping.tool.encry.Md5;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author John.zhang
 * @version Id: WeiXinPayController, v 1.0 2021/1/5 9:59 ZhiYong Exp $
 */

@RestController
@RequestMapping(value = "/weChat")
@CrossOrigin
public class WeChatPayController {

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    @Resource
    private WeChatPayService weChatPayService;

    @Resource
    private Signature signature;

    @Value("${pay.weChat.secret}")
    private String secret;

    /**
     * 查询订单支付状态
     *
     * @param outNo outNo
     * @return PayLog
     * @throws Exception
     */
    @GetMapping(value = "/result/{outNo}")
    public RespResult<PayLog> result(@PathVariable(value = "outNo") String outNo) throws Exception {
        PayLog payLog = weChatPayService.result(outNo);
        return RespResult.ok(payLog);
    }

    /**
     * 微信支付二维码获取
     *
     * @param content content
     * @return Map
     * @throws Exception
     */
    @GetMapping(value = "/pay")
    public RespResult<Map> pay(@RequestParam("content") String content) throws Exception {
        //content->AES->移除签名数据signature->MD5==signature
        Map<String, String> dataMap = signature.security(content);
        Map<String, String> map = weChatPayService.preOrder(dataMap);
        if (map != null) {
            map.put("orderNumber", dataMap.get("out_trade_no"));
            map.put("money", dataMap.get("total_fee"));
            return RespResult.ok(map);
        }
        return RespResult.error("支付系统繁忙，请稍后再试！");
    }


    /**
     * 支付结果回调
     * @return String
     */
    @PostMapping(value = "result")
    public String result(HttpServletRequest request) throws Exception {
        //网络流
        ByteArrayOutputStream os = getOutputStream(request);

        //将支付结果的XML结构转换成Map结构
        String xmlResult = new String(os.toByteArray(), StandardCharsets.UTF_8);
        Map<String, String> map = WXPayUtil.xmlToMap(xmlResult);
        System.out.println("xmlResult:"+xmlResult);
        //判断支付结果状态  日志状态：2 成功 ， 7 失败
        int status = 7;
        String returnCode = "return_code";
        if(map.get(returnCode).equals(WXPayConstants.SUCCESS) && map.get(returnCode).equals(WXPayConstants.SUCCESS)){
            status=2;
        }

        //创建日志对象
        PayLog payLog = new PayLog(map.get("out_trade_no"), status, JSON.toJSONString(map), map.get("out_trade_no"), new Date());

        //构建消息
        Message<String> message = MessageBuilder.withPayload(JSON.toJSONString(payLog)).build();
        //发消息
        rocketMQTemplate.sendMessageInTransaction(RocketConstants.PRODUCER_GROUP, RocketConstants.PAY_LOG_TOPIC, message, null);

        //Map 响应数据(这里是提供给微信的回调接口)
        Map<String,String> resultResp = new HashMap<>(16);
        resultResp.put("return_code","SUCCESS");
        resultResp.put("return_msg","OK");
        return WXPayUtil.mapToXml(resultResp);
    }


    /**
     * 申请退款状态
     * @param request request
     * @return String
     * @throws Exception Exception
     */
    @PostMapping(value = "/refund/result")
    public String refund(HttpServletRequest request) throws Exception{
        //网络流
        ByteArrayOutputStream os = getOutputStream(request);

        //将支付结果的XML结构转换成Map结构
        String xmlResult = new String(os.toByteArray(), StandardCharsets.UTF_8);
        Map<String, String> map = WXPayUtil.xmlToMap(xmlResult);
        System.out.println("退款数据-xmlResult:"+xmlResult);

        //获取退款信息（加密了-AES）
        String reqInfo = map.get("req_info");
        String key = Md5.md5(secret);
        byte[] decode = Aes.encryptAndDecrypt(Base64.decode(reqInfo), key, 2);
        System.out.println("退款解密后的数据："+new String(decode, StandardCharsets.UTF_8));

        //Map 响应数据
        Map<String,String> resultResp = new HashMap<>(16);
        resultResp.put("return_code","SUCCESS");
        resultResp.put("return_msg","OK");
        return WXPayUtil.mapToXml(resultResp);
    }


    private ByteArrayOutputStream getOutputStream(HttpServletRequest request) throws IOException {
        //读取网络输入流
        ServletInputStream is = request.getInputStream();
        //定义接收输入流对象（输出流）
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        //将网络输入流读取到输出流中
        byte[] buffer = new byte[1024];
        int len;
        while ((len=is.read(buffer))!=-1){
            os.write(buffer,0,len);
        }
        //关闭资源
        os.close();
        is.close();
        return os;
    }

}
